﻿using HalconDotNet;
using MvCamCtrl.NET;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using VisionBasicSystem.Commons;
using VisionBasicSystem.Model;
using VisionBasicSystem.Service;

namespace VisionBasicSystem
{
    public partial class Form1 : Form
    {
        //获取相机的信息
        private MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList;

        //获取相机的参数
        private MyCamera m_pMyCamera;

        private HTuple WindowID;

        //相机采集状态
        private bool m_bGrabbing;

        // ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver
        private UInt32 m_nBufSizeForDriver = 3072 * 2048 * 3;

        private byte[] m_pBufForDriver = new byte[3072 * 2048 * 3];

        // ch:用于保存图像的缓存 | en:Buffer for saving image
        private UInt32 m_nBufSizeForSaveImage = 3072 * 2048 * 3 * 3 + 2048;

        private byte[] m_pBufForSaveImage = new byte[3072 * 2048 * 3 * 3 + 2048];

        //--------------------------服务端变量------------

        private MySession cMySession = new MySession();

        private MyTcpServer cMyTcpServer = new MyTcpServer();
        public bool myThreadStop = true;

        //send or receive
        public byte[] myBy;//传递串口接收到的数据

        public int myByLenth = 0;//串口接收到的数据长度
        public string myStr;//串口接收的字符串

        //线程委托
        public delegate void MyInvoke(string str);

        //开始采集状态
        public bool StartGrabStatus = false;

        public Form1()
        {
            InitializeComponent();

            m_pDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
            m_bGrabbing = false;
            //运行窗口的时候，查找设备
            DeviceListAcq();

            //初始化偏移量，锡点值，标定点坐标
            InitializeDisposeData();

            //线程间操作无效从不是创建控件的线程访问它
            Control.CheckForIllegalCrossThreadCalls = false;

            Thread myThread = new Thread(ReceiveMsg);//创建新线程
            myThread.IsBackground = true;//线程后台运行
            myThread.Start();//启动线程
        }

        //初始化偏移量，标定数据，锡点露白面积
        public void InitializeDisposeData()
        {
            ImageDisposeDataService dataService = new ImageDisposeDataService();
            ImageDisposeData imageDispose = dataService.GetImageData();

            //初始化时设置标定偏移量，每次重新标定的时候再设置
            if (imageDispose != null)
            {
                X1offset_Nud.Value = Convert.ToDecimal(imageDispose.X1offset);
                Y1offset_Nud.Value = Convert.ToDecimal(imageDispose.Y1offset);
                X2offset_Nud.Value = Convert.ToDecimal(imageDispose.X2offset);
                Y2offset_Nud.Value = Convert.ToDecimal(imageDispose.Y2offset);
                X3offset_Nud.Value = Convert.ToDecimal(imageDispose.X3offset);
                Y3offset_Nud.Value = Convert.ToDecimal(imageDispose.Y3offset);
                X4offset_Nud.Value = Convert.ToDecimal(imageDispose.X4offset);
                Y4offset_Nud.Value = Convert.ToDecimal(imageDispose.Y4offset);
                //初始化时设置锡点值，每次重新设置锡点值
                //SetTinValue();
                TinValue.Text = imageDispose.TinValue.ToString();

                //初始化标定数据
                Qx_Column1.Value = imageDispose.Laser1x;
                Qx_Column2.Value = imageDispose.Laser2x;
                Qx_Column3.Value = imageDispose.Laser3x;
                Qx_Column4.Value = imageDispose.Laser4x;
                Qy_Row1.Value = imageDispose.Laser1y;
                Qy_Row2.Value = imageDispose.Laser2y;
                Qy_Row3.Value = imageDispose.Laser3y;
                Qy_Row4.Value = imageDispose.Laser4y;
            }

            //锡点露白面积
            RoiValueService roiService = new RoiValueService();
            RoiValue roiValue = roiService.GetRoiValue();
            if (roiValue != null)
            {
                roi_Row1.Value = roiValue.Row1;
                roi_Column1.Value = roiValue.Column1;
                roi_Row2.Value = roiValue.Row2;
                roi_Column2.Value = roiValue.Column2;
            }
        }

        #region 1.查找设备

        private void BnEnum_Click(object sender, EventArgs e)
        {
            DeviceListAcq();
        }

        private void DeviceListAcq()
        {
            int nRet;
            // ch:创建设备列表
            GC.Collect();
            cbDeviceList.Items.Clear();
            nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList);
            if (0 != nRet)
            {
                ShowErrorMsg("Enumerate devices fail!", 0);
                return;
            }

            // ch:在窗体列表中显示设备名
            for (int i = 0; i < m_pDeviceList.nDeviceNum; i++)
            {
                MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0);
                    MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                    if (gigeInfo.chUserDefinedName != "")
                    {
                        cbDeviceList.Items.Add("GigE: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")");
                    }
                    else
                    {
                        cbDeviceList.Items.Add("GigE: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")");
                    }
                }
                else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
                {
                    IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stUsb3VInfo, 0);
                    MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_USB3_DEVICE_INFO));
                    if (usbInfo.chUserDefinedName != "")
                    {
                        cbDeviceList.Items.Add("USB: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")");
                    }
                    else
                    {
                        cbDeviceList.Items.Add("USB: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")");
                    }
                }
            }

            // ch:选择第一项
            if (m_pDeviceList.nDeviceNum != 0)
            {
                cbDeviceList.SelectedIndex = 0;
            }
        }

        #endregion 1.查找设备

        #region 3.打开设备

        public void bnOpen_Click(object sender, EventArgs e)
        {
            if (m_pDeviceList.nDeviceNum == 0 || cbDeviceList.SelectedIndex == -1)
            {
                ShowErrorMsg("No device, please select", 0);
                return;
            }

            int nRet = -1;

            // ch:获取选择的设备信息 | en:Get selected device information
            MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(
                    m_pDeviceList.pDeviceInfo[cbDeviceList.SelectedIndex], typeof(MyCamera.MV_CC_DEVICE_INFO));

            // ch:打开设备 | en:Open device
            if (null == m_pMyCamera)
            {
                m_pMyCamera = new MyCamera();
                if (null == m_pMyCamera)
                {
                    return;
                }
            }

            nRet = m_pMyCamera.MV_CC_CreateDevice_NET(ref device);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            nRet = m_pMyCamera.MV_CC_OpenDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                m_pMyCamera.MV_CC_DestroyDevice_NET();
                ShowErrorMsg("设备打开失败!", nRet);
                return;
            }

            //设置心跳时间 最小500
            uint heartbeatTimeout = 500;
            nRet = m_pMyCamera.MV_CC_SetIntValue_NET("GevHeartbeatTimeout", heartbeatTimeout);
            if (MyCamera.MV_OK != nRet)
            {
                Console.WriteLine("Get Int Value failed:{0:x8}", nRet);
                return;
            }

            // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
            if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
            {
                int nPacketSize = m_pMyCamera.MV_CC_GetOptimalPacketSize_NET();
                if (nPacketSize > 0)
                {
                    nRet = m_pMyCamera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
                    if (nRet != MyCamera.MV_OK)
                    {
                        Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
                    }
                }
                else
                {
                    Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
                }
            }

            //TODO 海康大华实时采集设置
            // ch:设置采集连续模式,AcquisitionMode大华:0海康:2
            //采集模式0:SingleFrame 1:MultiFrame 2:Continuous
            m_pMyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", 0);

            //触发模式 0：Off 1：On
            m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerMode", 0);

            bnGetParam_Click(null, null);// ch:获取参数 | en:Get parameters

            // ch:控件操作 | en:Control operation
            SetCtrlWhenOpen();
        }

        private void SetCtrlWhenOpen()
        {
            bnOpen.Enabled = false;
            bnClose.Enabled = true;
            bnStartGrab.Enabled = true;
            bnStopGrab.Enabled = false;
            bnContinuesMode.Enabled = true;
            bnContinuesMode.Checked = true;
            bnTriggerMode.Enabled = true;
            cbSoftTrigger.Enabled = false;
            bnTriggerExec.Enabled = false;

            tbExposure.Enabled = true;
            tbGain.Enabled = true;
            tbFrameRate.Enabled = true;
            bnGetParam.Enabled = true;
            bnSetParam.Enabled = true;
        }

        #endregion 3.打开设备

        #region 4.关闭设备

        private void bnClose_Click(object sender, EventArgs e)
        {
            // ch:关闭设备
            int nRet;

            nRet = m_pMyCamera.MV_CC_CloseDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            nRet = m_pMyCamera.MV_CC_DestroyDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            // ch:控件操作
            SetCtrlWhenClose();

            // ch:取流标志位清零
            m_bGrabbing = false;
        }

        private void SetCtrlWhenClose()
        {
            bnOpen.Enabled = true;
            bnClose.Enabled = false;
            bnStartGrab.Enabled = false;
            bnStopGrab.Enabled = false;
            bnContinuesMode.Enabled = false;
            bnTriggerMode.Enabled = false;
            cbSoftTrigger.Enabled = false;
            bnTriggerExec.Enabled = false;
            bnSaveBmp.Enabled = false;
            bnSaveJpg.Enabled = false;
            tbExposure.Enabled = false;
            tbGain.Enabled = false;
            tbFrameRate.Enabled = false;
            bnGetParam.Enabled = false;
            bnSetParam.Enabled = false;
        }

        #endregion 4.关闭设备

        #region 5.连续采集

        private void bnContinuesMode_CheckedChanged(object sender, EventArgs e)
        {
            if (bnContinuesMode.Checked)
            {
                m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerMode", 0);
                cbSoftTrigger.Enabled = false;
                bnTriggerExec.Enabled = false;
                //ExternalTrigger.Enabled = true;
            }
        }

        #endregion 5.连续采集

        #region 6.触发模式

        private void bnTriggerMode_CheckedChanged(object sender, EventArgs e)
        {
            // ch:打开触发模式 | en:Open Trigger Mode
            if (bnTriggerMode.Checked)
            {
                m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerMode", 1);

                // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
                //           1 - Line1;
                //           2 - Line2;
                //           3 - Line3;
                //           4 - Counter;
                //           7 - Software;
                if (cbSoftTrigger.Checked)
                {
                    //外部触发TriggerActivation：1
                    //m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerActivation", 1);
                    //软触发TriggerSource：7
                    m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", 7);
                    if (m_bGrabbing)
                    {
                        bnTriggerExec.Enabled = true;
                    }
                }
                else
                {
                    m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", 0);
                }
                cbSoftTrigger.Enabled = true;
                //ExternalTrigger.Enabled = false;
            }
        }

        #endregion 6.触发模式

        #region 7.开始采集

        private void bnStartGrab_Click(object sender, EventArgs e)
        {
            int nRet;

            // ch:开始采集 | en:Start Grabbing
            nRet = m_pMyCamera.MV_CC_StartGrabbing_NET();
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Trigger Fail!", nRet);
                return;
            }

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStartGrab();

            // ch:标志位置位true | en:Set position bit true
            m_bGrabbing = true;

            // ch:显示 | en:Display
            nRet = m_pMyCamera.MV_CC_Display_NET(pictureBox1.Handle);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Display Fail！", nRet);
            }

            //采集状态
            StartGrabStatus = true;
        }

        #endregion 7.开始采集

        //外部触发
        /* private void ExternalTrigger_CheckedChanged(object sender, EventArgs e)
         {
             if (ExternalTrigger.Checked)
             {
                 //触发模式 0：Off 1：On
                 m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerMode", 1);
                 //上升沿触发
                 m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerActivation", 0);
                 cbSoftTrigger.Enabled = false;
                 bnTriggerExec.Enabled = false;
             }
         }*/

        #region 9.软触发

        private void cbSoftTrigger_CheckedChanged(object sender, EventArgs e)
        {
            if (cbSoftTrigger.Checked)
            {
                //外部触发TriggerActivation：1
                //m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerActivation", 1);
                //软触发TriggerSource：7
                m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", 7);
                if (m_bGrabbing)
                {
                    bnTriggerExec.Enabled = true;
                }
            }
            else
            {
                m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", 0);
                bnTriggerExec.Enabled = false;
            }
        }

        #endregion 9.软触发

        #region 10.软触发一次

        private void bnTriggerExec_Click(object sender, EventArgs e)
        {
            int nRet;

            // ch:触发命令
            nRet = m_pMyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Trigger Fail!", nRet);
            }
            else
            {
                //进行软触发后，处理图片，显示锡点露白面积
                SoftTrigAndSave();
            }
        }

        #endregion 10.软触发一次

        private void SetCtrlWhenStartGrab()
        {
            bnStartGrab.Enabled = false;
            bnStopGrab.Enabled = true;

            if (bnTriggerMode.Checked && cbSoftTrigger.Checked)
            {
                bnTriggerExec.Enabled = true;
            }

            bnSaveBmp.Enabled = true;
            bnSaveJpg.Enabled = true;
        }

        #region 8.停止采集

        private void bnStopGrab_Click(object sender, EventArgs e)
        {
            StopGrab();
        }

        private void StopGrab()
        {
            int nRet = -1;
            // ch:停止采集 | en:Stop Grabbing
            nRet = m_pMyCamera.MV_CC_StopGrabbing_NET();
            if (nRet != MyCamera.MV_OK)
            {
                ShowErrorMsg("Stop Grabbing Fail!", nRet);
            }

            // ch:标志位设为false | en:Set flag bit false
            m_bGrabbing = false;

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStopGrab();
        }

        private void SetCtrlWhenStopGrab()
        {
            bnStartGrab.Enabled = true;
            bnStopGrab.Enabled = false;

            bnTriggerExec.Enabled = false;

            bnSaveBmp.Enabled = false;
            bnSaveJpg.Enabled = false;
        }

        #endregion 8.停止采集

        #region 11.保存图片-Bmp

        private void bnSaveBmp_Click(object sender, EventArgs e)
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            MyCamera.MvGvspPixelType enDstPixelType;
            if (IsMonoData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            else if (IsColorData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            else
            {
                ShowErrorMsg("No such pixel type!", 0);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
            nRet = m_pMyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                //************************Mono8 转 Bitmap*******************************
                Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);

                ColorPalette cp = bmp.Palette;
                // init palette
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }
                // set palette back
                bmp.Palette = cp;

                bmp.Save("image1.bmp", ImageFormat.Bmp);
            }
            else
            {
                //*********************RGB8 转 Bitmap**************************
                for (int i = 0; i < stFrameInfo.nHeight; i++)
                {
                    for (int j = 0; j < stFrameInfo.nWidth; j++)
                    {
                        byte chRed = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3] = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2] = chRed;
                    }
                }
                try
                {
                    Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pImage);
                    bmp.Save("image1.bmp", ImageFormat.Bmp);
                }
                catch
                {
                }
            }
            ShowErrorMsg("Save Succeed!", 0);
        }

        private void SoftTrigAndSave()
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            MyCamera.MvGvspPixelType enDstPixelType;
            if (IsMonoData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            else if (IsColorData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            else
            {
                ShowErrorMsg("No such pixel type!", 0);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
            nRet = m_pMyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                //************************Mono8 转 Bitmap*******************************
                Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);

                ColorPalette cp = bmp.Palette;
                // 初始化调色板
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }
                //重新设置调色板
                bmp.Palette = cp;

                //将bmp图像转halcon图像，进行处理
                HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);

                object selectedItem = Product_Comb.SelectedItem;

                if (selectedItem == null)
                {
                    //产品1软触发
                    SoftDisposeImageProduct1(Image);
                }
                else
                {
                    string ProductModel = Product_Comb.SelectedItem.ToString();
                    if (string.Equals(ProductModel, "model1"))
                    {
                        //产品1软触发
                        SoftDisposeImageProduct1(Image);
                    }
                    else if (string.Equals(ProductModel, "model2"))
                    {
                        //产品2软触发
                        SoftDisposeImageProduct2(Image);
                    }
                }

                // 保存图片
                bmp.Save("image1.bmp", ImageFormat.Bmp);

                try
                {
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
            else
            {
                //*********************RGB8 转 Bitmap**************************
                for (int i = 0; i < stFrameInfo.nHeight; i++)
                {
                    for (int j = 0; j < stFrameInfo.nWidth; j++)
                    {
                        byte chRed = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3] = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2] = chRed;
                    }
                }
                try
                {
                    Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pImage);

                    //将bmp图像转halcon图像，进行处理
                    HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);
                    SoftDisposeImageProduct1(Image);

                    bmp.Save("image1.bmp", ImageFormat.Bmp);

                    //保存到特定路径下
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
            //ShowErrorMsg("采集完成！", 0);
        }

        //TODO 产品1软触发图片处理
        private void SoftDisposeImageProduct1(HObject ho_ReadImage)
        {
            // Local iconic variables（图形变量）
            HObject ho_MirrorImage, ho_Image, ho_ResultRegion, ho_ResultConnectedRegions;
            HObject ho_FillUpRegions, ho_ResultSelectedRegions, ho_Circle = null;
            HObject ho_ReduceCircleImage = null, ho_CircleRegion = null;
            HObject ho_ConnectedCircleRegion = null, ho_SelectedCircleRegion = null;
            HObject ho_ErosionCircleRegion = null, ho_ConnectionCircleRegion = null;
            HObject ho_SelectRegions = null;

            // Local control variables（控制变量）
            HTuple hv_T1 = null, hv_Width, hv_Height;
            HTuple hv_ResultArea = null, hv_ResultRow = null, hv_ResultColumn = null;
            HTuple hv_Number = null, hv_Soldering_Status = null, hv_i = null, hv_JudgeArea = null;
            HTuple hv_AreaRow = new HTuple(), hv_SelectArea = new HTuple();
            HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
            HTuple hv_Number1 = new HTuple(), hv_AreaSum = new HTuple();
            HTuple hv_j = new HTuple(), hv_T2 = null, hv_RunTime = null;

            //标定变量
            HTuple hv_HomMat2D = null, hv_Qx = null, hv_Qy = null;

            // Initialize local and output iconic variables（初始化本地和输出图标变量）
            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_FillUpRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);
            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.GenEmptyObj(out ho_ReduceCircleImage);
            HOperatorSet.GenEmptyObj(out ho_CircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ErosionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReadImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");
            //获取图像大小
            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            //阈值图像
            ho_ResultRegion.Dispose();
            HOperatorSet.Threshold(ho_Image, out ho_ResultRegion, 5, 160);
            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);
            //铺满区域
            ho_FillUpRegions.Dispose();
            HOperatorSet.FillUp(ho_ResultConnectedRegions, out ho_FillUpRegions);
            //选择面积
            ho_ResultSelectedRegions.Dispose();
            //TODO 产品1软触发阈值设置 正式150000：999999 测试15000：99999
            HOperatorSet.SelectShape(ho_FillUpRegions, out ho_ResultSelectedRegions,
                (new HTuple("area")).TupleConcat("circularity"), "and",
                (new HTuple(150000)).TupleConcat(0.75), (new HTuple(999999)).TupleConcat(1));
            //获取圆的中心坐标和面积
            HOperatorSet.AreaCenter(ho_ResultSelectedRegions, out hv_ResultArea, out hv_ResultRow, out hv_ResultColumn);

            //计算区域的个数
            HOperatorSet.CountObj(ho_ResultSelectedRegions, out hv_Number);

            //点锡结果判断 1：点锡OK 0：点锡NG
            hv_Soldering_Status = 0;

            HTuple end_val36 = hv_Number - 1;
            HTuple step_val36 = 1;
            //露白面积
            ArrayList JudgeArea = new ArrayList();

            for (hv_i = 0; hv_i.Continue(end_val36, step_val36); hv_i = hv_i.TupleAdd(step_val36))
            {
                hv_AreaRow = hv_ResultRow.TupleSelect(hv_i);
                ho_Circle.Dispose();
                HOperatorSet.GenCircle(out ho_Circle, hv_AreaRow, hv_ResultColumn.TupleSelect(hv_i),
                    ((((hv_ResultArea.TupleSelect(hv_i)) / 3.1415926)).TupleSqrt()) / 2);
                ho_ReduceCircleImage.Dispose();
                HOperatorSet.ReduceDomain(ho_Image, ho_Circle, out ho_ReduceCircleImage);
                //阈值图像
                ho_CircleRegion.Dispose();
                HOperatorSet.Threshold(ho_ReduceCircleImage, out ho_CircleRegion, 230, 255);
                //区域连通处理
                ho_ConnectedCircleRegion.Dispose();
                HOperatorSet.Connection(ho_CircleRegion, out ho_ConnectedCircleRegion);
                ho_SelectedCircleRegion.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedCircleRegion, out ho_SelectedCircleRegion, "area", "and", 600, 15000);

                //用矩形结构元素腐蚀
                ho_ErosionCircleRegion.Dispose();
                HOperatorSet.ErosionRectangle1(ho_SelectedCircleRegion, out ho_ErosionCircleRegion, 3, 3);

                ho_ConnectionCircleRegion.Dispose();
                HOperatorSet.Connection(ho_ErosionCircleRegion, out ho_ConnectionCircleRegion);
                //选择面积
                ho_SelectRegions.Dispose();
                HOperatorSet.SelectShape(ho_ConnectionCircleRegion, out ho_SelectRegions, "area", "and", 500, 15000);

                HOperatorSet.AreaCenter(ho_SelectRegions, out hv_SelectArea, out hv_Row, out hv_Column);
                //计算区域的个数
                HOperatorSet.CountObj(ho_SelectRegions, out hv_Number1);

                //判断露白区域面积
                hv_AreaSum = 0;
                HTuple end_val63 = hv_Number1 - 1;
                HTuple step_val63 = 1;
                for (hv_j = 0; hv_j.Continue(end_val63, step_val63); hv_j = hv_j.TupleAdd(step_val63))
                {
                    hv_AreaSum = hv_AreaSum + (hv_SelectArea.TupleSelect(hv_j));
                }
                if ((int)(new HTuple(hv_AreaSum.TupleGreater(Convert.ToInt32(TinValue.Text)))) != 0)
                {
                    if (hv_Soldering_Status == null)
                        hv_Soldering_Status = new HTuple();
                    hv_Soldering_Status[hv_i] = 0;
                }
                else if ((int)(new HTuple(hv_AreaSum.TupleLess(Convert.ToInt32(TinValue.Text)))) != 0)
                {
                    if (hv_Soldering_Status == null)
                        hv_Soldering_Status = new HTuple();
                    hv_Soldering_Status[hv_i] = 1;
                }

                if (hv_JudgeArea == null)
                {
                    hv_JudgeArea = new HTuple();
                }
                JudgeArea.Add(hv_AreaSum);
            }

            dev_update_on();

            HOperatorSet.CountSeconds(out hv_T2);

            hv_RunTime = (hv_T2 - hv_T1) * 1000;

            ho_ReadImage.Dispose();
            ho_MirrorImage.Dispose();
            ho_Image.Dispose();
            ho_ResultRegion.Dispose();
            ho_ResultConnectedRegions.Dispose();
            ho_FillUpRegions.Dispose();
            ho_ResultSelectedRegions.Dispose();
            ho_Circle.Dispose();
            ho_ReduceCircleImage.Dispose();
            ho_CircleRegion.Dispose();
            ho_ConnectedCircleRegion.Dispose();
            ho_SelectedCircleRegion.Dispose();
            ho_ErosionCircleRegion.Dispose();
            ho_ConnectionCircleRegion.Dispose();
            ho_SelectRegions.Dispose();

            //读取标定数据
            hv_HomMat2D = ReadValue();

            HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_ResultColumn, hv_ResultRow, out hv_Qx, out hv_Qy);

            QxColumn = hv_Qx;
            QyRow = hv_Qy;

            if (QxColumn.Length > 0 || QyRow.Length > 0)
            {
                Px_Column1.Value = decimal.Round(decimal.Parse(QxColumn[0].ToString()), 2);
                Px_Column2.Value = decimal.Round(decimal.Parse(QxColumn[1].ToString()), 2);
                Px_Column3.Value = decimal.Round(decimal.Parse(QxColumn[2].ToString()), 2);
                Px_Column4.Value = decimal.Round(decimal.Parse(QxColumn[3].ToString()), 2);

                Py_Row1.Value = decimal.Round(decimal.Parse(QyRow[0].ToString()), 2);
                Py_Row2.Value = decimal.Round(decimal.Parse(QyRow[1].ToString()), 2);
                Py_Row3.Value = decimal.Round(decimal.Parse(QyRow[2].ToString()), 2);
                Py_Row4.Value = decimal.Round(decimal.Parse(QyRow[3].ToString()), 2);
            }

            //显示面积值
            int length = JudgeArea.Count;

            if (length == 1)
            {
                Point1_Txt.Text = JudgeArea[0].ToString();
            }
            else if (length == 2)
            {
                Point1_Txt.Text = JudgeArea[0].ToString();
                Point2_Txt.Text = JudgeArea[1].ToString();
            }
            else if (length == 3)
            {
                Point1_Txt.Text = JudgeArea[0].ToString();
                Point2_Txt.Text = JudgeArea[1].ToString();
                Point3_Txt.Text = JudgeArea[2].ToString();
            }
            else if (length == 4)
            {
                Point1_Txt.Text = JudgeArea[0].ToString();
                Point2_Txt.Text = JudgeArea[1].ToString();
                Point3_Txt.Text = JudgeArea[2].ToString();
                Point4_Txt.Text = JudgeArea[3].ToString();
            }
        }

        //TODO 产品2软触发图片处理

        private void SoftDisposeImageProduct2(HObject ho_ReadImage)
        {
            // Local iconic variables（图形变量）
            HObject ho_Rectangle, ho_ReduceImage, ho_RegionTrans;
            HObject ho_MirrorImage, ho_Image, ho_ResultRegion, ho_ResultConnectedRegions;
            HObject ho_ResultSelectedRegions;

            // Local control variables（控制变量）
            HTuple hv_T1 = null, hv_Width = null, hv_Height = null;
            HTuple hv_ResultArea = null, hv_ResultRow = null, hv_ResultColumn = null;
            HTuple hv_Number = null, hv_Row1 = null, hv_Column1 = null;
            HTuple hv_Row2 = null;
            HTuple hv_Column2 = null;
            HTuple hv_Row3 = null, hv_Column3 = null;
            HTuple hv_Row4 = null, hv_Column4 = null;
            HTuple hv_T2 = null, hv_RunTime = null;

            HTuple hv_UsedThreshold = null;

            // Initialize local and output iconic variables（初始化本地和输出图标变量）
            HOperatorSet.GenEmptyObj(out ho_RegionTrans);
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ReduceImage);
            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //获取图像大小
            HOperatorSet.GetImageSize(ho_ReadImage, out hv_Width, out hv_Height);

            //region矩形
            //ho_Rectangle.Dispose();
            //HOperatorSet.GenRectangle1(out ho_Rectangle, Convert.ToInt32(roi_Row1.Value), Convert.ToInt32(roi_Column1.Value),
            //Convert.ToInt32(roi_Row2.Value), Convert.ToInt32(roi_Column2.Value));
            ////获得矩形的图像
            //ho_ReduceImage.Dispose();
            //HOperatorSet.ReduceDomain(ho_ReadImage, ho_Rectangle, out ho_ReduceImage);
            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReadImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");

            //阈值图像
            //threshold (Image, ResultRegion, 0, 120)
            ho_ResultRegion.Dispose();
            HOperatorSet.BinaryThreshold(ho_Image, out ho_ResultRegion, "smooth_histo", "dark", out hv_UsedThreshold);

            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);

            try
            {
                ho_ResultSelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ResultConnectedRegions, out ho_ResultSelectedRegions,
                    ((new HTuple("area")).TupleConcat("dist_mean")).TupleConcat("roundness"), "and",
                    ((new HTuple(810000)).TupleConcat(300)).TupleConcat(0.6), ((new HTuple(1500000)).TupleConcat(800)).TupleConcat(1));

                ho_RegionTrans.Dispose();
                HOperatorSet.ShapeTrans(ho_ResultSelectedRegions, out ho_RegionTrans, "convex");

                //获取圆的中心坐标和面积
                HOperatorSet.AreaCenter(ho_RegionTrans, out hv_ResultArea, out hv_ResultRow, out hv_ResultColumn);

                //计算区域的个数
                HOperatorSet.CountObj(ho_RegionTrans, out hv_Number);

                //点锡结果判断 1：点锡OK 0：点锡NG
                //识别点1露白面积
                //343,317
                hv_Row1 = hv_ResultRow - 358;
                hv_Column1 = hv_ResultColumn - 315;
                int[] Area1 = RecognitionTinArea(ho_Image, hv_Row1, hv_Column1);
                if (Area1.Length > 0)
                {
                    //显示点1露白面积
                    Point1_Txt.Text = Area1[0].ToString();
                }
                else
                {
                    //显示点1露白面积
                    Point1_Txt.Text = "0";
                }

                //识别点2露白面积
                //341,317
                hv_Row2 = hv_ResultRow - 350;
                hv_Column2 = hv_ResultColumn + 328;

                int[] Area2 = RecognitionTinArea(ho_Image, hv_Row2, hv_Column2);
                if (Area2.Length > 0)
                {
                    //显示点2露白面积
                    Point2_Txt.Text = Area2[0].ToString();
                }
                else
                {
                    //显示点2露白面积
                    Point2_Txt.Text = "0";
                }

                //识别点3露白面积338,318
                hv_Row3 = hv_ResultRow + 342;
                hv_Column3 = hv_ResultColumn - 325;

                int[] Area3 = RecognitionTinArea(ho_Image, hv_Row3, hv_Column3);
                if (Area3.Length > 0)
                {
                    //显示点3露白面积
                    Point3_Txt.Text = Area3[0].ToString();
                }
                else
                {
                    //显示点3露白面积
                    Point3_Txt.Text = "0";
                }

                //识别点4露白面积
                hv_Row4 = hv_ResultRow + 346;
                hv_Column4 = hv_ResultColumn + 320;

                int[] Area4 = RecognitionTinArea(ho_Image, hv_Row4, hv_Column4);
                if (Area4.Length > 0)
                {
                    //显示点4露白面积
                    Point4_Txt.Text = Area4[0].ToString();
                }
                else
                {
                    //显示点4露白面积
                    Point4_Txt.Text = "0";
                }

                dev_update_on();

                HOperatorSet.CountSeconds(out hv_T2);

                hv_RunTime = (hv_T2 - hv_T1) * 1000;

                sw.Stop();
                sw.Reset();
            }
            catch (Exception e)
            {
                MessageBox.Show("请检查图像参数设置");
                LogHelper.WriteLog("图片识别错误", e);
            }

            ho_ReadImage.Dispose();
            ho_Rectangle.Dispose();
            ho_ReduceImage.Dispose();
            ho_MirrorImage.Dispose();
            ho_Image.Dispose();
            ho_ResultRegion.Dispose();
            ho_ResultConnectedRegions.Dispose();
            ho_ResultSelectedRegions.Dispose();
        }

        private Boolean IsMonoData(MyCamera.MvGvspPixelType enGvspPixelType)
        {
            switch (enGvspPixelType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    return true;

                default:
                    return false;
            }
        }

        private Boolean IsColorData(MyCamera.MvGvspPixelType enGvspPixelType)
        {
            switch (enGvspPixelType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YCBCR411_8_CBYYCRYY:
                    return true;

                default:
                    return false;
            }
        }

        #endregion 11.保存图片-Bmp

        #region 12.保存图片-jpg

        private void bnSaveJpg_Click(object sender, EventArgs e)
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_SAVE_IMAGE_PARAM_EX stSaveParam = new MyCamera.MV_SAVE_IMAGE_PARAM_EX();
            stSaveParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg;
            stSaveParam.enPixelType = stFrameInfo.enPixelType;
            stSaveParam.pData = pData;
            stSaveParam.nDataLen = stFrameInfo.nFrameLen;
            stSaveParam.nHeight = stFrameInfo.nHeight;
            stSaveParam.nWidth = stFrameInfo.nWidth;
            stSaveParam.pImageBuffer = pImage;
            stSaveParam.nBufferSize = m_nBufSizeForSaveImage;
            stSaveParam.nJpgQuality = 80;
            nRet = m_pMyCamera.MV_CC_SaveImageEx_NET(ref stSaveParam);

            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Save Fail!", 0);
                return;
            }

            try
            {
                FileStream file = new FileStream("image.jpg", FileMode.Create, FileAccess.Write);
                file.Write(m_pBufForSaveImage, 0, (int)stSaveParam.nImageLen);
                file.Close();
            }
            catch
            {
            }
            ShowErrorMsg("Save Succeed!", 0);
        }

        #endregion 12.保存图片-jpg

        #region 13.获取相机参数

        private void bnGetParam_Click(object sender, EventArgs e)
        {
            // 查询相机参数
            CameraParamService paramService = new CameraParamService();
            CameraParam param = paramService.GetCameraParam();
            int exposure = param.Exposure;
            decimal gain = param.Gain;
            int frameRate = param.FrameRate;
            tbExposure.Text = exposure.ToString();
            tbGain.Text = gain.ToString();
            tbFrameRate.Text = frameRate.ToString();

            //设置参数
            SetCameraParam(exposure, float.Parse(gain.ToString()), frameRate);

            /*MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
            int nRet = m_pMyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                tbExposure.Text = stParam.fCurValue.ToString("F1");
            }

            nRet = m_pMyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                m_pMyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
                tbGain.Text = stParam.fCurValue.ToString("F1");
            }

            nRet = m_pMyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
            if (MyCamera.MV_OK == nRet)
            {
                m_pMyCamera.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);
                //tbFrameRate.Text = stParam.fCurValue.ToString("F1");
                tbFrameRate.Text = "7";
            }*/
        }

        #endregion 13.获取相机参数

        #region 14.设置相机参数

        private void bnSetParam_Click(object sender, EventArgs e)
        {
            int nRet;
            m_pMyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);

            float exposure;
            float gain;
            float frameRate;
            try
            {
                exposure = float.Parse(tbExposure.Text);
                gain = float.Parse(tbGain.Text);
                frameRate = float.Parse(tbFrameRate.Text);
            }
            catch
            {
                ShowErrorMsg("请输入正确的类型!", 0);
                return;
            }

            nRet = SetCameraParam(exposure, gain, frameRate);

            if (nRet == 0)
            {
                //保存到数据库
                CameraParam cameraParam = new CameraParam();

                cameraParam.Exposure = Convert.ToInt32(exposure);
                cameraParam.Gain = Convert.ToDecimal(tbGain.Text);
                cameraParam.FrameRate = Convert.ToInt32(frameRate);

                CameraParamService paramService = new CameraParamService();
                if (paramService.SetCameraParam(cameraParam))
                {
                    ShowErrorMsg("参数设置成功!", 0);
                }
            }
        }

        private int SetCameraParam(float exposure, float gain, float frameRate)
        {
            //曝光
            int nRet = m_pMyCamera.MV_CC_SetFloatValue_NET("ExposureTime", exposure);
            if (nRet != MyCamera.MV_OK)
            {
                ShowErrorMsg("设置曝光失败!", nRet);
            }

            //增益
            m_pMyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
            nRet = m_pMyCamera.MV_CC_SetFloatValue_NET("Gain", gain);
            if (nRet != MyCamera.MV_OK)
            {
                ShowErrorMsg("设置增益失败!", nRet);
            }

            nRet = m_pMyCamera.MV_CC_SetFloatValue_NET("AcquisitionFrameRate", frameRate);
            if (nRet != MyCamera.MV_OK)
            {
                ShowErrorMsg("设置帧率失败!", nRet);
            }

            return nRet;
        }

        #endregion 14.设置相机参数

        //-----------------------------------服务端监听-----------------------------------

        /// <summary>
        /// 服务端监听客户端发送的数据
        /// </summary>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            MyNetListen();
        }

        /// <summary>
        /// 系统服务作为服务端监听客户端接口
        /// </summary>
        private void MyNetListen()
        {
            //byte[] data = new byte[1024];
            if (btnConnect.Text.Trim() == "启动监听")
            {
                OpenListen();
                rtbMySendMessage.Enabled = false;
                rtbReceiveMsg.Enabled = false;
                textBox1.Enabled = false;
                textBox2.Enabled = false;
                textBox3.Enabled = false;
                textBox4.Enabled = false;
            }
            else
            {
                CloseListen();
            }
        }

        //启动监听
        public void OpenListen()
        {
            btnConnect.Text = "断开连接";
            this.pictureBox2.Image = Image.FromFile(Application.StartupPath + "\\Resources\\green.png");//bin文件中

            cMyTcpServer.OpenServer(Convert.ToInt32(txbServerPort.Text.Trim()));
            LogHelper.WriteLog("启动监听");
        }

        //关闭监听
        private void CloseListen()
        {
            try
            {
                btnConnect.Text = "启动监听";
                this.pictureBox2.Image = Image.FromFile(Application.StartupPath + "\\Resources\\red.png");//bin文件中
                cMyTcpServer.CloseServer();
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("断开连接异常", e);
            }
        }

        //TODO 开始计时
        public Stopwatch sw = new Stopwatch();

        public Stopwatch sw1 = new Stopwatch();

        //接收处理线程部分
        public void ReceiveMsg()
        {
            while (myThreadStop)
            {
                string myRecvStrTemp = "";
                Dictionary<string, MySession> ClientSocket = cMyTcpServer.dic_ClientSocket;

                #region
                lock (ClientSocket)
                {
                    try
                    {
                        List<string> sessionValue = new List<string>(ClientSocket.Keys);
                        for (int i = 0; i < sessionValue.Count; i++)
                        {
                            string session = sessionValue[i].Trim();
                            //foreach (var item in cMyTcpServer.dic_ClientSocket)
                            //cMySession = item.Value;//两种方法都可以item.Key.ToString()
                            if (cMyTcpServer.dic_ClientSocket.TryGetValue(session, out cMySession) == true)
                            {
                                byte[] myReceByte = cMySession.GetBuffer(0, cMySession.m_Buffer.Count);//提取接收数据

                                //数据处理
                                if (myReceByte.Length > 0)
                                {
                                    //开始计时
                                    sw.Start();
                                    sw1.Start();

                                    StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建，定义到外面。
                                    //直接按ASCII规则转换成字符串
                                    builder.Append(Encoding.ASCII.GetString(myReceByte));
                                    //追加的形式添加到文本框末端，并滚动到最后。
                                    myRecvStrTemp = builder.ToString();//字符串输出
                                    TrigerPicture(myRecvStrTemp);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        LogHelper.WriteLog("数据接收异常", e);
                    }
                }
                #endregion 真正使用的接收线程处理部分
                showMsg(myRecvStrTemp);
            }
        }

        public void showMsg(string msg)//接收显示处理部分
        {
            {
                //在线程里以安全方式调用控件
                if ((rtbReceiveMsg.InvokeRequired))
                {
                    MyInvoke _myinvoke = new MyInvoke(showMsg);
                    rtbReceiveMsg.Invoke(_myinvoke, new object[] { msg });
                }
                else
                {
                    rtbReceiveMsg.Text = msg;//显示部分
                }
            }
        }

        /// <summary>
        /// 发送测试数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMySendMessage_Click(object sender, EventArgs e)
        {
            int m_length = rtbMySendMessage.Text.Trim().Length;
            byte[] data = new byte[m_length];
            data = Encoding.UTF8.GetBytes(rtbMySendMessage.Text);
            lock (cMyTcpServer.dic_ClientSocket)
            {
                foreach (var item in cMyTcpServer.dic_ClientSocket)
                {
                    cMyTcpServer.SendData(item.Key.ToString(), data);
                }
            }
        }

        /// <summary>
        /// 发送相机处理结果给labview系统
        /// </summary>
        /// <param name="sendData"></param>
        private void SendDataToClient(string sendData)
        {
            try
            {
                int m_length = sendData.Length;
                byte[] data = new byte[m_length];
                data = Encoding.UTF8.GetBytes(sendData);
                lock (cMyTcpServer.dic_ClientSocket)
                {
                    foreach (var item in cMyTcpServer.dic_ClientSocket)
                    {
                        cMyTcpServer.SendData(item.Key.ToString(), data);
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("给labview发送数据异常", e);
            }
        }

        //定义路径名变量
        //private string pathname = string.Empty;

        private HTuple a, b, c, WindowHandle;
        private HObject circle;

        //创建圆形ROI
        private void CreateMode_Button_Click(object sender, EventArgs e)
        {
            //pictureBox1.Handle,获取pictureBox1的句柄
            HOperatorSet.OpenWindow(0, 0, pictureBox1.Width, pictureBox1.Height, pictureBox1.Handle, "visible", "", out WindowHandle);
            HOperatorSet.DrawCircle(WindowHandle, out a, out b, out c);
            HOperatorSet.GenCircle(out circle, a, b, c);
            HOperatorSet.SetColor(WindowHandle, "yellow");

            //半径
            this.roi_Row1.Value = Convert.ToDecimal(c.ToString());
            //行坐标
            this.roi_Row2.Value = Convert.ToDecimal(a.ToString());
            //列坐标
            this.roi_Column2.Value = Convert.ToDecimal(b.ToString());
        }

        //----------------------------------------处理图片-----------------------------

        //图像实际坐标
        private double[] QxColumn = null;

        private double[] QyRow = null;

        //焊锡点
        private int[] tinStatus = null;

        //行列坐标
        private double[] RowY = null;

        private double[] ColumnX = null;

        public void dev_update_off()
        {
            return;
        }

        public void dev_update_on()
        {
            return;
        }

        /// <summary>
        /// 读取标定数据
        /// </summary>
        /// <returns></returns>
        public double[] ReadValue()
        {
            //string demarcateTxtValue = File.ReadAllText(Application.StartupPath + "\\Argu\\CalibrationValue.txt");

            CalibrationValueService calibrationService = new CalibrationValueService();
            CalibrationValue calibration = calibrationService.GetCalibrationValue();
            string calibrationValue = calibration.Value;
            double[] value = null;
            if (calibrationValue != null)
            {
                string[] arr = calibrationValue.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                List<double> value1 = new List<double>();
                foreach (var item in arr)
                {
                    double d1 = Convert.ToDouble(item);
                    value1.Add(d1);
                }
                value = value1.ToArray();
            }
            return value;
        }

        //触发自动拍照
        public void TrigerPicture(string myStr)
        {
            if (string.Equals(myStr, "Trig"))
            {
                object selectedItem = Product_Comb.SelectedItem;

                if (selectedItem == null)
                {
                    //触发相机拍照，自动处理图片
                    TriggerAuto();
                }
                else
                {
                    string ProductModel = Product_Comb.SelectedItem.ToString();
                    if (string.Equals(ProductModel, "model1"))
                    {
                        //触发相机拍照，自动处理图片
                        TriggerAuto();
                    }
                    else if (string.Equals(ProductModel, "model2"))
                    {
                        //触发相机拍照，自动处理图片
                        TriggerAutoProduct2();
                    }
                }
            }
        }

        //自动触发相机进行拍照
        private void TriggerAuto()
        {
            //触发拍照采集
            OpenTrigger();

            //自动触发，bmp转halcon，处理图片，保存
            AutoDisposeImageAndSave();
        }

        //自动触发拍照
        private void OpenTrigger()
        {
            //判断相机是否连接
            bool bIsConnect = m_pMyCamera.MV_CC_IsDeviceConnected_NET();
            if (!bIsConnect)
            {
                //打开设备
                OpenEquipment();
            }

            //判断采集状态
            if (!StartGrabStatus)
            {
                //开始采集
                StartGrab();
            }
            //软触发一次
            TriggerExec();
        }

        //自动触发，bmp转halcon，处理图片，保存
        public void AutoDisposeImageAndSave()
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            MyCamera.MvGvspPixelType enDstPixelType;
            if (IsMonoData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            else if (IsColorData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            else
            {
                ShowErrorMsg("没有这样的像素类型!", 0);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
            nRet = m_pMyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                //************************Mono8 转 Bitmap*******************************
                Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);

                ColorPalette cp = bmp.Palette;
                // 初始化调色板
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }
                //重新设置调色板
                bmp.Palette = cp;
                // 将bmp图像转halcon图像，进行处理
                HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);
                AutoDisposeImage(Image);

                // 保存图片
                bmp.Save("image1.bmp", ImageFormat.Bmp);
                try
                {
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
        }

        //TODO 产品1自动触发采集处理图片
        private void AutoDisposeImage(HObject ho_ReadImage)
        {
            sw1.Stop();
            sw1.Reset();

            // Local iconic variables（图形变量）
            HObject ho_Rectangle, ho_ReduceImage;
            HObject ho_MirrorImage, ho_Image, ho_ResultRegion, ho_ResultConnectedRegions;
            HObject ho_FillUpRegions, ho_ResultSelectedRegions, ho_Circle = null;
            HObject ho_ReduceCircleImage = null, ho_CircleRegion = null;
            HObject ho_ConnectedCircleRegion = null, ho_SelectedCircleRegion = null;
            HObject ho_ErosionCircleRegion = null, ho_ConnectionCircleRegion = null;
            HObject ho_SelectRegions = null;

            // Local control variables（控制变量）
            HTuple hv_T1 = null;
            HTuple hv_ResultArea = null, hv_ResultRow = null, hv_ResultColumn = null;
            HTuple hv_Number = null, hv_Soldering_Status = null, hv_i = null, hv_JudgeArea = null;
            HTuple hv_AreaRow = new HTuple(), hv_SelectArea = new HTuple();
            HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
            HTuple hv_Number1 = new HTuple(), hv_AreaSum = new HTuple();
            HTuple hv_j = new HTuple(), hv_T2 = null, hv_RunTime = null;

            //标定变量
            HTuple hv_HomMat2D = null, hv_Qx = null, hv_Qy = null;

            // Initialize local and output iconic variables（初始化本地和输出图标变量）
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ReduceImage);
            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_FillUpRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);
            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.GenEmptyObj(out ho_ReduceCircleImage);
            HOperatorSet.GenEmptyObj(out ho_CircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ErosionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //region矩形
            ho_Rectangle.Dispose();
            HOperatorSet.GenRectangle1(out ho_Rectangle, Convert.ToInt32(roi_Row1.Value), Convert.ToInt32(roi_Column1.Value),
                Convert.ToInt32(roi_Row2.Value), Convert.ToInt32(roi_Column2.Value));
            //获得矩形的图像
            ho_ReduceImage.Dispose();
            HOperatorSet.ReduceDomain(ho_ReadImage, ho_Rectangle, out ho_ReduceImage);
            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReduceImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");
            //获取图像大小
            //HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            //阈值图像
            ho_ResultRegion.Dispose();
            HOperatorSet.Threshold(ho_Image, out ho_ResultRegion, 5, 160);
            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);
            //铺满区域
            ho_FillUpRegions.Dispose();
            HOperatorSet.FillUp(ho_ResultConnectedRegions, out ho_FillUpRegions);
            //选择面积
            ho_ResultSelectedRegions.Dispose();

            //TODO 产品1自动触发阈值设置 测试：15000,0.75,99999;生产：150000
            HOperatorSet.SelectShape(ho_FillUpRegions, out ho_ResultSelectedRegions,
                (new HTuple("area")).TupleConcat("circularity"), "and",
                (new HTuple(150000)).TupleConcat(0.75), (new HTuple(999999)).TupleConcat(1));
            //获取圆的中心坐标和面积
            HOperatorSet.AreaCenter(ho_ResultSelectedRegions, out hv_ResultArea, out hv_ResultRow, out hv_ResultColumn);

            if (hv_ResultArea.Length == 4)
            {
                //计算区域的个数
                HOperatorSet.CountObj(ho_ResultSelectedRegions, out hv_Number);

                //点锡结果判断 1：点锡OK 0：点锡NG
                hv_Soldering_Status = 0;

                HTuple end_val36 = hv_Number - 1;
                HTuple step_val36 = 1;
                //露白面积
                ArrayList JudgeArea = new ArrayList();

                for (hv_i = 0; hv_i.Continue(end_val36, step_val36); hv_i = hv_i.TupleAdd(step_val36))
                {
                    hv_AreaRow = hv_ResultRow.TupleSelect(hv_i);
                    ho_Circle.Dispose();
                    HOperatorSet.GenCircle(out ho_Circle, hv_AreaRow, hv_ResultColumn.TupleSelect(hv_i),
                        ((((hv_ResultArea.TupleSelect(hv_i)) / 3.1415926)).TupleSqrt()) / 2);
                    ho_ReduceCircleImage.Dispose();
                    HOperatorSet.ReduceDomain(ho_Image, ho_Circle, out ho_ReduceCircleImage);
                    //阈值图像
                    ho_CircleRegion.Dispose();
                    HOperatorSet.Threshold(ho_ReduceCircleImage, out ho_CircleRegion, 230, 255);
                    //区域连通处理
                    ho_ConnectedCircleRegion.Dispose();
                    HOperatorSet.Connection(ho_CircleRegion, out ho_ConnectedCircleRegion);
                    ho_SelectedCircleRegion.Dispose();
                    HOperatorSet.SelectShape(ho_ConnectedCircleRegion, out ho_SelectedCircleRegion, "area", "and", 600, 9999);

                    //用矩形结构元素腐蚀
                    ho_ErosionCircleRegion.Dispose();
                    HOperatorSet.ErosionRectangle1(ho_SelectedCircleRegion, out ho_ErosionCircleRegion, 3, 3);

                    ho_ConnectionCircleRegion.Dispose();
                    HOperatorSet.Connection(ho_ErosionCircleRegion, out ho_ConnectionCircleRegion);
                    //选择面积
                    ho_SelectRegions.Dispose();
                    HOperatorSet.SelectShape(ho_ConnectionCircleRegion, out ho_SelectRegions, "area", "and", 500, 9999);

                    HOperatorSet.AreaCenter(ho_SelectRegions, out hv_SelectArea, out hv_Row, out hv_Column);
                    //计算区域的个数
                    HOperatorSet.CountObj(ho_SelectRegions, out hv_Number1);

                    //判断露白区域面积
                    hv_AreaSum = 0;
                    HTuple end_val63 = hv_Number1 - 1;
                    HTuple step_val63 = 1;
                    for (hv_j = 0; hv_j.Continue(end_val63, step_val63); hv_j = hv_j.TupleAdd(step_val63))
                    {
                        hv_AreaSum = hv_AreaSum + (hv_SelectArea.TupleSelect(hv_j));
                    }
                    if ((int)(new HTuple(hv_AreaSum.TupleGreater(Convert.ToInt32(TinValue.Text)))) != 0)
                    {
                        if (hv_Soldering_Status == null)
                            hv_Soldering_Status = new HTuple();
                        hv_Soldering_Status[hv_i] = 0;
                    }
                    else if ((int)(new HTuple(hv_AreaSum.TupleLess(Convert.ToInt32(TinValue.Text)))) != 0)
                    {
                        if (hv_Soldering_Status == null)
                            hv_Soldering_Status = new HTuple();
                        hv_Soldering_Status[hv_i] = 1;
                    }

                    if (hv_JudgeArea == null)
                    {
                        hv_JudgeArea = new HTuple();
                    }
                    JudgeArea.Add(hv_AreaSum);
                }

                dev_update_on();

                HOperatorSet.CountSeconds(out hv_T2);

                hv_RunTime = (hv_T2 - hv_T1) * 1000;

                ho_ReadImage.Dispose();
                ho_Rectangle.Dispose();
                ho_ReduceImage.Dispose();
                ho_MirrorImage.Dispose();
                ho_Image.Dispose();
                ho_ResultRegion.Dispose();
                ho_ResultConnectedRegions.Dispose();
                ho_FillUpRegions.Dispose();
                ho_ResultSelectedRegions.Dispose();
                ho_Circle.Dispose();
                ho_ReduceCircleImage.Dispose();
                ho_CircleRegion.Dispose();
                ho_ConnectedCircleRegion.Dispose();
                ho_SelectedCircleRegion.Dispose();
                ho_ErosionCircleRegion.Dispose();
                ho_ConnectionCircleRegion.Dispose();
                ho_SelectRegions.Dispose();

                //读取标定数据
                hv_HomMat2D = ReadValue();

                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_ResultColumn, hv_ResultRow, out hv_Qx, out hv_Qy);

                RowY = hv_Qy;
                ColumnX = hv_Qx;
                //判断焊锡点
                tinStatus = hv_Soldering_Status;

                StringBuilder sb = new StringBuilder();

                sb.Append("Start");

                for (int i = 0; i < ColumnX.Length; i++)
                {
                    if (ColumnX != null)
                    {
                        double cx = ColumnX[i];
                        double xValue = Math.Round(cx, 2);
                        double x = xValue + Convert.ToDouble(X1offset_Nud.Value);
                        sb.Append("x:").Append(Utils.PolishingStrData(x.ToString())).Append(";");
                    }
                    if (RowY != null)
                    {
                        double ry = RowY[i];
                        double yValue = Math.Round(ry, 2);
                        double y = yValue + Convert.ToDouble(Y1offset_Nud.Value);
                        sb.Append("y:").Append(Utils.PolishingStrData(y.ToString())).Append(";");
                    }
                    if (tinStatus != null)
                    {
                        sb.Append("inspect:").Append(tinStatus[i]);
                    }
                }

                if (tinStatus.Length < 4)
                {
                    for (int j = 0; j < 4 - tinStatus.Length; j++)
                    {
                        sb.Append("x:0099.99;y:0099.99;inspect:0");
                    }
                }

                sb.Append("End");

                //向PLC发送 坐标 判断结果
                SendDataToClient(sb.ToString());

                sw.Stop();
                //textBox5.Text = sw.Elapsed.ToString();
                sw.Reset();

                //显示面积值
                int length = JudgeArea.Count;

                if (length == 1)
                {
                    Point1_Txt.Text = JudgeArea[0].ToString();
                }
                else if (length == 2)
                {
                    Point1_Txt.Text = JudgeArea[0].ToString();
                    Point2_Txt.Text = JudgeArea[1].ToString();
                }
                else if (length == 3)
                {
                    Point1_Txt.Text = JudgeArea[0].ToString();
                    Point2_Txt.Text = JudgeArea[1].ToString();
                    Point3_Txt.Text = JudgeArea[2].ToString();
                }
                else if (length == 4)
                {
                    Point1_Txt.Text = JudgeArea[0].ToString();
                    Point2_Txt.Text = JudgeArea[1].ToString();
                    Point3_Txt.Text = JudgeArea[2].ToString();
                    Point4_Txt.Text = JudgeArea[3].ToString();
                }
            }
            else
            {
                MessageBox.Show("请查看拍照点是否到位");
                StringBuilder sb = new StringBuilder();
                sb.Append("Start");
                for (int j = 0; j < 4; j++)
                {
                    sb.Append("x:0099.99;y:0099.99;inspect:0");
                }
                sb.Append("End");

                //向PLC发送 坐标 判断结果
                SendDataToClient(sb.ToString());
            }
        }

        public string SaveImageAssignDirectory()
        {
            //完整路径
            string path = new StringBuilder()
                .Append(Application.StartupPath).Append("\\").Append("Image").Append("\\")
                .Append(DateTime.Now.ToString("yyyy-MM-dd")).ToString();

            if (!Directory.Exists(path))//如果不存在就创建file文件夹
            {
                Directory.CreateDirectory(path);
            }
            string LogDate = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff");
            string imagePath = new StringBuilder().Append(path).Append("\\").Append(LogDate).Append(".bmp").ToString();
            return imagePath;
        }

        //产品2拍照采集
        private void TriggerAutoProduct2()
        {
            //触发拍照采集
            OpenTrigger();

            //产品2，bmp转halcon，处理图片，保存
            DisposeImageAndSaveProduct2();
        }

        //产品2，bmp转halcon，处理图片，保存
        public void DisposeImageAndSaveProduct2()
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            MyCamera.MvGvspPixelType enDstPixelType;
            if (IsMonoData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            else if (IsColorData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            else
            {
                ShowErrorMsg("没有这样的像素类型!", 0);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
            nRet = m_pMyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                //************************Mono8 转 Bitmap*******************************
                Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);

                ColorPalette cp = bmp.Palette;
                // 初始化调色板
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }
                //重新设置调色板
                bmp.Palette = cp;

                //将bmp图像转halcon图像，进行处理
                HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);
                LoadImageProduct2(Image);

                // 保存图片
                bmp.Save("image1.bmp", ImageFormat.Bmp);

                //调试模板用
                //HOperatorSet.ReadImage(out Image1, Application.StartupPath + CameraConstants.LOAD_IMAGE);
                //LoadImageProduct2(Image1);

                try
                {
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
            else
            {
                //*********************RGB8 转 Bitmap**************************
                for (int i = 0; i < stFrameInfo.nHeight; i++)
                {
                    for (int j = 0; j < stFrameInfo.nWidth; j++)
                    {
                        byte chRed = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3] = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2] = chRed;
                    }
                }
                try
                {
                    Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pImage);
                    bmp.Save("image1.bmp", ImageFormat.Bmp);

                    //将bmp图像转halcon图像，进行处理
                    HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);
                    LoadImageProduct2(Image);

                    //保存到特定路径下
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
        }

        //TODO 产品2自动触发采集处理图片
        private void LoadImageProduct2(HObject ho_ReadImage)
        {
            sw1.Stop();
            sw1.Reset();

            // Local iconic variables（图形变量）
            HObject ho_Rectangle, ho_ReduceImage, ho_RegionTrans;
            HObject ho_MirrorImage, ho_Image, ho_ResultRegion, ho_ResultConnectedRegions;
            HObject ho_ResultSelectedRegions;

            // Local control variables（控制变量）
            HTuple hv_T1 = null, hv_Width = null, hv_Height = null;
            HTuple hv_ResultArea = null, hv_ResultRow = null, hv_ResultColumn = null;
            HTuple hv_Number = null, hv_Row1 = null, hv_Column1 = null;
            HTuple hv_SolderingStatus1 = new HTuple(), hv_Row2 = null;
            HTuple hv_Column2 = null, hv_SolderingStatus2 = new HTuple();
            HTuple hv_Row3 = null, hv_Column3 = null, hv_SolderingStatus3 = new HTuple();
            HTuple hv_Row4 = null, hv_Column4 = null, hv_SolderingStatus4 = new HTuple();
            HTuple hv_T2 = null, hv_RunTime = null;

            HTuple hv_UsedThreshold = null;
            //标定变量
            HTuple hv_HomMat2D = null;
            //标定变量
            HTuple hv_Qx1 = null, hv_Qy1 = null;
            HTuple hv_Qx2 = null, hv_Qy2 = null;
            HTuple hv_Qx3 = null, hv_Qy3 = null;
            HTuple hv_Qx4 = null, hv_Qy4 = null;

            // Initialize local and output iconic variables（初始化本地和输出图标变量）
            HOperatorSet.GenEmptyObj(out ho_RegionTrans);
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ReduceImage);
            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //获取图像大小
            HOperatorSet.GetImageSize(ho_ReadImage, out hv_Width, out hv_Height);
            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReadImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");

            //阈值图像
            //threshold (Image, ResultRegion, 0, 120)
            ho_ResultRegion.Dispose();
            HOperatorSet.BinaryThreshold(ho_Image, out ho_ResultRegion, "smooth_histo", "dark", out hv_UsedThreshold);

            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);

            try
            {
                ho_ResultSelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ResultConnectedRegions, out ho_ResultSelectedRegions,
                    ((new HTuple("area")).TupleConcat("dist_mean")).TupleConcat("roundness"), "and",
                    ((new HTuple(810000)).TupleConcat(300)).TupleConcat(0.6), ((new HTuple(1500000)).TupleConcat(800)).TupleConcat(1));

                ho_RegionTrans.Dispose();
                HOperatorSet.ShapeTrans(ho_ResultSelectedRegions, out ho_RegionTrans, "convex");
                //铺满区域
                //fill_up (ResultConnectedRegions, FillUpRegions)

                //获取圆的中心坐标和面积
                HOperatorSet.AreaCenter(ho_RegionTrans, out hv_ResultArea, out hv_ResultRow, out hv_ResultColumn);

                //计算区域的个数
                HOperatorSet.CountObj(ho_RegionTrans, out hv_Number);

                //点锡结果判断 1：点锡OK 0：点锡NG
                //识别点1露白面积
                //343,317
                hv_Row1 = hv_ResultRow - 358;
                hv_Column1 = hv_ResultColumn - 315;

                int SolderingStatus1 = 0;

                int[] Area1 = RecognitionTinArea(ho_Image, hv_Row1, hv_Column1);
                if (Area1.Length > 0)
                {
                    if (Area1[0] > Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus1 = 0;
                    }
                    else if (Area1[0] < Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus1 = 1;
                    }
                    //显示点1露白面积
                    Point1_Txt.Text = Area1[0].ToString();
                }
                else
                {
                    SolderingStatus1 = 1;
                    //显示点1露白面积
                    Point1_Txt.Text = "0";
                }

                StringBuilder sb = new StringBuilder();

                sb.Append("Start");

                //读取标定数据
                hv_HomMat2D = ReadValue();

                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_Column1, hv_Row1, out hv_Qx1, out hv_Qy1);

                double cx1 = hv_Qx1[0];
                double xValue1 = Math.Round(cx1, 2);
                double x1 = xValue1 + Convert.ToDouble(X1offset_Nud.Value);

                double ry1 = hv_Qy1[0];
                double yValue1 = Math.Round(ry1, 2);
                double y1 = yValue1 + Convert.ToDouble(Y1offset_Nud.Value);

                sb.Append("x:").Append(Utils.PolishingStrData(x1.ToString())).Append(";")
                                   .Append("y:").Append(Utils.PolishingStrData(y1.ToString())).Append(";")
                                   .Append("inspect:").Append(SolderingStatus1);

                //识别点2露白面积
                //341,317
                hv_Row2 = hv_ResultRow - 350;
                hv_Column2 = hv_ResultColumn + 328;

                int SolderingStatus2 = 0;
                int[] Area2 = RecognitionTinArea(ho_Image, hv_Row2, hv_Column2);
                if (Area2.Length > 0)
                {
                    if (Area2[0] > Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus2 = 0;
                    }
                    else if (Area2[0] < Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus2 = 1;
                    }
                    //显示点2露白面积
                    Point2_Txt.Text = Area2[0].ToString();
                }
                else
                {
                    SolderingStatus2 = 1;
                    //显示点2露白面积
                    Point2_Txt.Text = "0";
                }

                //读取标定数据
                hv_HomMat2D = ReadValue();

                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_Column2, hv_Row2, out hv_Qx2, out hv_Qy2);

                double cx2 = hv_Qx2[0];
                double xValue2 = Math.Round(cx2, 2);
                double x2 = xValue2 + Convert.ToDouble(X2offset_Nud.Value);
                double ry2 = hv_Qy2[0];
                double yValue2 = Math.Round(ry2, 2);
                double y2 = yValue2 + Convert.ToDouble(Y2offset_Nud.Value);

                sb.Append("x:").Append(Utils.PolishingStrData(x2.ToString())).Append(";")
                    .Append("y:").Append(Utils.PolishingStrData(y2.ToString())).Append(";")
                    .Append("inspect:").Append(SolderingStatus2);

                //识别点3露白面积338,318
                hv_Row3 = hv_ResultRow + 342;
                hv_Column3 = hv_ResultColumn - 325;

                int SolderingStatus3 = 0;
                int[] Area3 = RecognitionTinArea(ho_Image, hv_Row3, hv_Column3);
                if (Area3.Length > 0)
                {
                    if (Area3[0] > Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus3 = 0;
                    }
                    else if (Area3[0] < Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus3 = 1;
                    }
                    //显示点3露白面积
                    Point3_Txt.Text = Area3[0].ToString();
                }
                else
                {
                    SolderingStatus3 = 1;
                    //显示点3露白面积
                    Point3_Txt.Text = "0";
                }

                //读取标定数据
                hv_HomMat2D = ReadValue();

                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_Column3, hv_Row3, out hv_Qx3, out hv_Qy3);

                double cx3 = hv_Qx3[0];
                double xValue3 = Math.Round(cx3, 2);
                double x3 = xValue3 + Convert.ToDouble(X3offset_Nud.Value);
                double ry3 = hv_Qy3[0];
                double yValue3 = Math.Round(ry3, 2);
                double y3 = yValue3 + Convert.ToDouble(Y3offset_Nud.Value);

                sb.Append("x:").Append(Utils.PolishingStrData(x3.ToString())).Append(";")
                    .Append("y:").Append(Utils.PolishingStrData(y3.ToString())).Append(";")
                    .Append("inspect:").Append(SolderingStatus3);

                //识别点4露白面积
                hv_Row4 = hv_ResultRow + 346;
                hv_Column4 = hv_ResultColumn + 320;

                int SolderingStatus4 = 0;
                int[] Area4 = RecognitionTinArea(ho_Image, hv_Row4, hv_Column4);
                if (Area4.Length > 0)
                {
                    if (Area4[0] > Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus4 = 0;
                    }
                    else if (Area4[0] < Convert.ToInt32(TinValue.Text))
                    {
                        SolderingStatus4 = 1;
                    }
                    //显示点4露白面积
                    Point4_Txt.Text = Area4[0].ToString();
                }
                else
                {
                    SolderingStatus4 = 1;
                    //显示点4露白面积
                    Point4_Txt.Text = "0";
                }

                //读取标定数据
                hv_HomMat2D = ReadValue();

                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_Column4, hv_Row4, out hv_Qx4, out hv_Qy4);

                double cx4 = hv_Qx4[0];
                double xValue4 = Math.Round(cx4, 2);
                double x4 = xValue4 + Convert.ToDouble(X4offset_Nud.Value);
                double ry4 = hv_Qy4[0];
                double yValue4 = Math.Round(ry4, 2);
                double y4 = yValue4 + Convert.ToDouble(Y4offset_Nud.Value);

                sb.Append("x:").Append(Utils.PolishingStrData(x4.ToString())).Append(";")
                    .Append("y:").Append(Utils.PolishingStrData(y4.ToString())).Append(";")
                    .Append("inspect:").Append(SolderingStatus4);

                dev_update_on();

                HOperatorSet.CountSeconds(out hv_T2);

                hv_RunTime = (hv_T2 - hv_T1) * 1000;

                sb.Append("End");

                hv_RunTime = (hv_T2 - hv_T1) * 1000;

                //向PLC发送 坐标 判断结果
                SendDataToClient(sb.ToString());

                sw.Stop();
                //textBox5.Text = sw.Elapsed.ToString();
                sw.Reset();
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("图片识别错误", e);
                StringBuilder sb = new StringBuilder();
                sb.Append("Start");
                for (int j = 0; j < 4; j++)
                {
                    sb.Append("x:0000.00;y:0000.00;inspect:0");
                }
                sb.Append("End");

                //向PLC发送 坐标 判断结果
                SendDataToClient(sb.ToString());
            }

            ho_ReadImage.Dispose();
            ho_Rectangle.Dispose();
            ho_ReduceImage.Dispose();
            ho_MirrorImage.Dispose();
            ho_Image.Dispose();
            ho_ResultRegion.Dispose();
            ho_ResultConnectedRegions.Dispose();
            ho_ResultSelectedRegions.Dispose();
        }

        //识别锡点露白面积判断
        public int[] RecognitionTinArea(HObject ho_Image, HTuple hv_Row, HTuple hv_Column)
        {
            HTuple hv_Area = null, hv_AreaRow = null, hv_AreaColumn = null;

            HObject ho_Circle, ho_ReduceCircleImage, ho_CircleRegion, ho_ConnectedCircleRegion;
            HObject ho_SelectedCircleRegion, ho_ErosionCircleRegion, ho_ConnectionCircleRegion, ho_SelectedRegions;

            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.GenEmptyObj(out ho_ReduceCircleImage);
            HOperatorSet.GenEmptyObj(out ho_CircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectedCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ErosionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_ConnectionCircleRegion);
            HOperatorSet.GenEmptyObj(out ho_SelectedRegions);

            ho_Circle.Dispose();
            HOperatorSet.GenCircle(out ho_Circle, hv_Row, hv_Column, 100.5);
            ho_ReduceCircleImage.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_Circle, out ho_ReduceCircleImage);
            //阈值图像
            ho_CircleRegion.Dispose();
            HOperatorSet.Threshold(ho_ReduceCircleImage, out ho_CircleRegion, 250, 255);
            //HOperatorSet.BinaryThreshold(ho_ReduceCircleImage4, out ho_CircleRegion4, "smooth_histo", "light", out hv_UsedThreshold4);
            //区域连通处理
            ho_ConnectedCircleRegion.Dispose();
            HOperatorSet.Connection(ho_CircleRegion, out ho_ConnectedCircleRegion);
            ho_SelectedCircleRegion.Dispose();
            HOperatorSet.SelectShape(ho_ConnectedCircleRegion, out ho_SelectedCircleRegion, "area", "and", 600, 18000);

            //用矩形结构元素腐蚀
            ho_ErosionCircleRegion.Dispose();
            HOperatorSet.ErosionRectangle1(ho_SelectedCircleRegion, out ho_ErosionCircleRegion, 3, 3);
            ho_ConnectionCircleRegion.Dispose();
            HOperatorSet.Connection(ho_ErosionCircleRegion, out ho_ConnectionCircleRegion);
            //选择面积
            ho_SelectedRegions.Dispose();
            HOperatorSet.SelectShape(ho_ConnectionCircleRegion, out ho_SelectedRegions, "area", "and", 500, 18000);

            HOperatorSet.AreaCenter(ho_SelectedRegions, out hv_Area, out hv_AreaRow, out hv_AreaColumn);
            int[] Area = hv_Area;
            return Area;
        }

        #region 标定

        /**
         * 步骤
         * 1调用自动模式-通过相机采集样板图片
         * 2.点击标定
         *   将标定坐标和实际坐标
         *   像素坐标和机械坐标的矩阵关系图 HomMat2D值
         * 3.将HomMat2D值保存
         */

        private void Demarcate_Btn_Click(object sender, EventArgs e)
        {
            DemarcateTrigger();
        }

        //标定触发相机进行拍照
        private void DemarcateTrigger()
        {
            //触发拍照采集
            OpenTrigger();
            //标定，bmp转halcon，处理图片，保存
            DisposeImageAndSaveDemarcate();
        }

        //标定，bmp转halcon，处理图片，保存
        public void DisposeImageAndSaveDemarcate()
        {
            int nRet;
            UInt32 nPayloadSize = 0;
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = m_pMyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Get PayloadSize failed", nRet);
                return;
            }
            nPayloadSize = stParam.nCurValue;
            if (nPayloadSize > m_nBufSizeForDriver)
            {
                m_nBufSizeForDriver = nPayloadSize;
                m_pBufForDriver = new byte[m_nBufSizeForDriver];

                // ch:同时对保存图像的缓存做大小判断处理 | en:Determine the buffer size to save image
                // ch:BMP图片大小：width * height * 3 + 2048(预留BMP头大小) | en:BMP image size: width * height * 3 + 2048 (Reserved for BMP header)
                m_nBufSizeForSaveImage = m_nBufSizeForDriver * 3 + 2048;
                m_pBufForSaveImage = new byte[m_nBufSizeForSaveImage];
            }

            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForDriver, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();

            // ch:超时获取一帧，超时时间为1秒 | en:Get one frame timeout, timeout is 1 sec
            nRet = m_pMyCamera.MV_CC_GetOneFrameTimeout_NET(pData, m_nBufSizeForDriver, ref stFrameInfo, 1000);
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("No Data!", nRet);
                return;
            }

            MyCamera.MvGvspPixelType enDstPixelType;
            if (IsMonoData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
            }
            else if (IsColorData(stFrameInfo.enPixelType))
            {
                enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
            }
            else
            {
                ShowErrorMsg("没有这样的像素类型!", 0);
                return;
            }

            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(m_pBufForSaveImage, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
            nRet = m_pMyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                //************************Mono8 转 Bitmap*******************************
                Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);

                ColorPalette cp = bmp.Palette;
                // 初始化调色板
                for (int i = 0; i < 256; i++)
                {
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                }
                //重新设置调色板
                bmp.Palette = cp;

                // 将bmp图像转halcon图像，进行处理
                HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);

                object selectedItem = Product_Comb.SelectedItem;

                if (selectedItem == null)
                {
                    //产品1标定
                    DisposeImageDemarcateProduct1(Image);
                }
                else
                {
                    string ProductModel = Product_Comb.SelectedItem.ToString();
                    if (string.Equals(ProductModel, "model1"))
                    {
                        //产品1标定
                        DisposeImageDemarcateProduct1(Image);
                    }
                    else if (string.Equals(ProductModel, "model2"))
                    {
                        //产品2标定
                        DisposeImageDemarcateProduct2(Image);
                    }
                }

                // 保存图片
                bmp.Save("image1.bmp", ImageFormat.Bmp);

                // 标定测试
                /*HOperatorSet.ReadImage(out Image1, Application.StartupPath + CameraConstants.LOAD_IMAGE);
                DisposeImageDemarcateProduct2(Image1);*/
                try
                {
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
            else
            {
                //*********************RGB8 转 Bitmap**************************
                for (int i = 0; i < stFrameInfo.nHeight; i++)
                {
                    for (int j = 0; j < stFrameInfo.nWidth; j++)
                    {
                        byte chRed = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3] = m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2];
                        m_pBufForSaveImage[i * stFrameInfo.nWidth * 3 + j * 3 + 2] = chRed;
                    }
                }
                try
                {
                    Bitmap bmp = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pImage);
                    bmp.Save("image1.bmp", ImageFormat.Bmp);

                    //将bmp图像转halcon图像，进行处理
                    HObject Image = BitmapToHobject(bmp.Width, bmp.Height, bmp);
                    //处理标定图片
                    DisposeImageDemarcateProduct1(Image);

                    //保存到特定路径下
                    string imagePath = SaveImageAssignDirectory();
                    bmp.Save(imagePath, ImageFormat.Bmp);
                }
                catch
                {
                }
            }
        }

        //TODO 产品1-标定
        private void DisposeImageDemarcateProduct1(HObject ho_ReadImage)
        {
            // Local iconic variables
            HObject ho_MirrorImage, ho_Image, ho_ResultRegion, ho_ResultConnectedRegions;
            HObject ho_FillUpRegions, ho_ResultSelectedRegions, ho_SortedRegions;

            // Local control variables

            HTuple hv_T1 = null, hv_Area = null, hv_Row = null;
            HTuple hv_Column = null, hv_Column1 = null, hv_Row1 = null;
            HTuple hv_HomMat2D = null, hv_Qx = null, hv_Qy = null;
            HTuple hv_T2 = null, hv_RunTime = null;

            // Initialize local and output iconic variables

            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_FillUpRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);
            HOperatorSet.GenEmptyObj(out ho_SortedRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //region矩形
            //ho_Rectangle.Dispose();
            //HOperatorSet.GenRectangle1(out ho_Rectangle, 630, 80, 2300, 3800);
            ////获得矩形的图像
            //ho_ReduceImage.Dispose();
            //HOperatorSet.ReduceDomain(ho_ReadImage, ho_Rectangle, out ho_ReduceImage);
            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReadImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");
            //获取图像大小
            //HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            //阈值图像
            ho_ResultRegion.Dispose();
            HOperatorSet.Threshold(ho_Image, out ho_ResultRegion, 5, 160);
            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);
            //铺满区域
            ho_FillUpRegions.Dispose();
            HOperatorSet.FillUp(ho_ResultConnectedRegions, out ho_FillUpRegions);
            //选择面积
            ho_ResultSelectedRegions.Dispose();

            //TODO 产品1标定阈值设置 测试：15000,0.75,99999;生产：150000
            HOperatorSet.SelectShape(ho_FillUpRegions, out ho_ResultSelectedRegions,
                (new HTuple("area")).TupleConcat("circularity"), "and",
                (new HTuple(15000)).TupleConcat(0.75), (new HTuple(99999)).TupleConcat(1));
            //获取圆的中心坐标和面积
            HOperatorSet.AreaCenter(ho_ResultSelectedRegions, out hv_Area, out hv_Row, out hv_Column);

            //-----------得到机械手的坐标
            //求出这个像素坐标和机械坐标的对应关系
            //像素坐标Px-->Column,Py-->Row
            //9点实际坐标Qx-->Column1,Qy-->Row1
            hv_Column1 = new HTuple();
            hv_Column1[0] = Convert.ToDouble(Qx_Column1.Value);
            hv_Column1[1] = Convert.ToDouble(Qx_Column2.Value);
            hv_Column1[2] = Convert.ToDouble(Qx_Column3.Value);
            hv_Column1[3] = Convert.ToDouble(Qx_Column4.Value);

            hv_Row1 = new HTuple();
            hv_Row1[0] = Convert.ToDouble(Qy_Row1.Value);
            hv_Row1[1] = Convert.ToDouble(Qy_Row2.Value);
            hv_Row1[2] = Convert.ToDouble(Qy_Row3.Value);
            hv_Row1[3] = Convert.ToDouble(Qy_Row4.Value);

            //保存标定坐标值
            ImageDisposeDataService disposeDataService = new ImageDisposeDataService();
            ImageDisposeData disposeData = new ImageDisposeData();
            disposeData.Laser1x = Qx_Column1.Value;
            disposeData.Laser2x = Qx_Column2.Value;
            disposeData.Laser3x = Qx_Column3.Value;
            disposeData.Laser4x = Qx_Column4.Value;

            disposeData.Laser1y = Qy_Row1.Value;
            disposeData.Laser2y = Qy_Row2.Value;
            disposeData.Laser3y = Qy_Row3.Value;
            disposeData.Laser4y = Qy_Row4.Value;

            disposeDataService.UpdateCalibrationValue(disposeData);

            try
            {
                //计算标定数据
                HOperatorSet.VectorToHomMat2d(hv_Column, hv_Row, hv_Column1, hv_Row1, out hv_HomMat2D);
                //根据HomMat2D计算 标定的实际坐标
                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_Column, hv_Row, out hv_Qx, out hv_Qy);
                QxColumn = hv_Qx;
                QyRow = hv_Qy;

                Px_Column1.Value = decimal.Round(decimal.Parse(QxColumn[0].ToString()), 2);
                Px_Column2.Value = decimal.Round(decimal.Parse(QxColumn[1].ToString()), 2);
                Px_Column3.Value = decimal.Round(decimal.Parse(QxColumn[2].ToString()), 2);
                Px_Column4.Value = decimal.Round(decimal.Parse(QxColumn[3].ToString()), 2);

                Py_Row1.Value = decimal.Round(decimal.Parse(QyRow[0].ToString()), 2);
                Py_Row2.Value = decimal.Round(decimal.Parse(QyRow[1].ToString()), 2);
                Py_Row3.Value = decimal.Round(decimal.Parse(QyRow[2].ToString()), 2);
                Py_Row4.Value = decimal.Round(decimal.Parse(QyRow[3].ToString()), 2);

                //计算出标定关系值
                double[] calibrationValue = hv_HomMat2D;
                if (calibrationValue.Length > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (var item in calibrationValue)
                    {
                        //标定的数据以；隔开，不去掉最后一个；
                        sb.Append(Convert.ToString(item)).Append(";");
                    }
                    CalibrationValueService valueService = new CalibrationValueService();
                    CalibrationValue calibration = new CalibrationValue();
                    calibration.Value = sb.ToString();
                    if (valueService.UpdateCalibrationValue(calibration))
                    {
                        ShowErrorMsg("标定完成！", 0);
                    }
                }

                HOperatorSet.CountSeconds(out hv_T2);

                hv_RunTime = (hv_T2 - hv_T1) * 1000;
                ho_ReadImage.Dispose();
                //ho_Rectangle.Dispose();
                //ho_ReduceImage.Dispose();
                ho_MirrorImage.Dispose();
                ho_Image.Dispose();
                ho_ResultRegion.Dispose();
                ho_ResultConnectedRegions.Dispose();
                ho_FillUpRegions.Dispose();
                ho_ResultSelectedRegions.Dispose();
                ho_SortedRegions.Dispose();

                //将标定数据写入txt文件中
                /* StreamWriter sw1 = new StreamWriter(Application.StartupPath + "\\Argu\\CalibrationValue.txt");

                 StringBuilder sb = new StringBuilder();
                 foreach (var item in calibrationValue)
                 {
                     //标定的数据以；隔开，不去掉最后一个；
                     sb.Append(Convert.ToString(item)).Append(";");
                 }
                 sw1.Write(sb.ToString());
                 sw1.Close();*/
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("标定失败,", e);
            }
        }

        //TODO 产品2标定
        private void DisposeImageDemarcateProduct2(HObject ho_ReadImage)
        {
            // Local iconic variables
            HObject ho_MirrorImage, ho_Image, ho_FillUpRegions;
            HObject ho_ResultRegion, ho_ResultConnectedRegions, ho_ResultSelectedRegions;

            // Local control variables
            HTuple hv_T1 = null, hv_Width = null, hv_Height = null, hv_UsedThreshold = null;
            HTuple hv_ResultArea = null, hv_ResultColumn1 = null, hv_ResultRow1 = null, hv_Column1 = null;
            HTuple hv_Row1 = null, hv_HomMat2D = null, hv_Qx = null, hv_Qy = null;

            // Initialize local and output iconic variables
            HOperatorSet.GenEmptyObj(out ho_FillUpRegions);
            HOperatorSet.GenEmptyObj(out ho_MirrorImage);
            HOperatorSet.GenEmptyObj(out ho_Image);
            HOperatorSet.GenEmptyObj(out ho_ResultRegion);
            HOperatorSet.GenEmptyObj(out ho_ResultConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_ResultSelectedRegions);

            dev_update_off();

            HOperatorSet.CountSeconds(out hv_T1);

            //对图像进行旋转
            ho_MirrorImage.Dispose();
            HOperatorSet.MirrorImage(ho_ReadImage, out ho_MirrorImage, "row");
            ho_Image.Dispose();
            HOperatorSet.RotateImage(ho_MirrorImage, out ho_Image, 270, "constant");
            //获取图像大小
            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            //阈值图像
            ho_ResultRegion.Dispose();
            //HOperatorSet.Threshold(ho_Image, out ho_ResultRegion, 250, 255);
            HOperatorSet.BinaryThreshold(ho_Image, out ho_ResultRegion, "max_separability", "light", out hv_UsedThreshold);
            //区域连通处理
            ho_ResultConnectedRegions.Dispose();
            HOperatorSet.Connection(ho_ResultRegion, out ho_ResultConnectedRegions);
            try
            {
                //选择面积
                ho_ResultSelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ResultConnectedRegions, out ho_ResultSelectedRegions,
                    (new HTuple("area")).TupleConcat("roundness"), "and", (new HTuple(7000)).TupleConcat(0.6), (new HTuple(12000)).TupleConcat(1));
                //获取圆的中心坐标和面积
                HOperatorSet.AreaCenter(ho_ResultSelectedRegions, out hv_ResultArea, out hv_ResultRow1, out hv_ResultColumn1);

                //-----------得到机械手的坐标
                //求出这个像素坐标和机械坐标的对应关系
                //像素坐标Px-->Column,Py-->Row
                //9点实际坐标Qx-->Column1,Qy-->Row1
                hv_Column1 = new HTuple();
                hv_Column1[0] = Convert.ToDouble(Qx_Column1.Value);
                hv_Column1[1] = Convert.ToDouble(Qx_Column2.Value);
                hv_Column1[2] = Convert.ToDouble(Qx_Column3.Value);
                hv_Column1[3] = Convert.ToDouble(Qx_Column4.Value);

                hv_Row1 = new HTuple();
                hv_Row1[0] = Convert.ToDouble(Qy_Row1.Value);
                hv_Row1[1] = Convert.ToDouble(Qy_Row2.Value);
                hv_Row1[2] = Convert.ToDouble(Qy_Row3.Value);
                hv_Row1[3] = Convert.ToDouble(Qy_Row4.Value);

                //保存标定坐标值
                ImageDisposeDataService disposeDataService = new ImageDisposeDataService();
                ImageDisposeData disposeData = new ImageDisposeData();
                disposeData.Laser1x = Qx_Column1.Value;
                disposeData.Laser2x = Qx_Column2.Value;
                disposeData.Laser3x = Qx_Column3.Value;
                disposeData.Laser4x = Qx_Column4.Value;

                disposeData.Laser1y = Qy_Row1.Value;
                disposeData.Laser2y = Qy_Row2.Value;
                disposeData.Laser3y = Qy_Row3.Value;
                disposeData.Laser4y = Qy_Row4.Value;

                disposeDataService.UpdateCalibrationValue(disposeData);

                //计算标定数据
                HOperatorSet.VectorToHomMat2d(hv_ResultColumn1, hv_ResultRow1, hv_Column1, hv_Row1, out hv_HomMat2D);

                //根据HomMat2D计算 标定的实际坐标
                HOperatorSet.AffineTransPoint2d(hv_HomMat2D, hv_ResultColumn1, hv_ResultRow1, out hv_Qx, out hv_Qy);
                QxColumn = hv_Qx;
                QyRow = hv_Qy;

                Px_Column1.Value = decimal.Round(decimal.Parse(QxColumn[0].ToString()), 2);
                Px_Column2.Value = decimal.Round(decimal.Parse(QxColumn[1].ToString()), 2);
                Px_Column3.Value = decimal.Round(decimal.Parse(QxColumn[2].ToString()), 2);
                Px_Column4.Value = decimal.Round(decimal.Parse(QxColumn[3].ToString()), 2);

                Py_Row1.Value = decimal.Round(decimal.Parse(QyRow[0].ToString()), 2);
                Py_Row2.Value = decimal.Round(decimal.Parse(QyRow[1].ToString()), 2);
                Py_Row3.Value = decimal.Round(decimal.Parse(QyRow[2].ToString()), 2);
                Py_Row4.Value = decimal.Round(decimal.Parse(QyRow[3].ToString()), 2);

                //计算出标定关系值
                double[] calibrationValue = hv_HomMat2D;
                if (calibrationValue.Length > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (var item in calibrationValue)
                    {
                        //标定的数据以；隔开，不去掉最后一个；
                        sb.Append(Convert.ToString(item)).Append(";");
                    }
                    CalibrationValueService valueService = new CalibrationValueService();
                    CalibrationValue calibration = new CalibrationValue();
                    calibration.Value = sb.ToString();
                    if (valueService.UpdateCalibrationValue(calibration))
                    {
                        ShowErrorMsg("标定完成！", 0);
                    }
                }

                ho_MirrorImage.Dispose();
                ho_Image.Dispose();
                ho_ResultRegion.Dispose();
                ho_ResultConnectedRegions.Dispose();
                ho_ResultSelectedRegions.Dispose();
            }
            catch (Exception e)
            {
                MessageBox.Show("请检查图像参数设置");
                LogHelper.WriteLog("标定失败,", e);
            }
        }

        /// <summary>
        /// 打开设备
        /// </summary>
        public void OpenEquipment()
        {
            if (m_pDeviceList.nDeviceNum == 0 || cbDeviceList.SelectedIndex == -1)
            {
                ShowErrorMsg("请选择设备！", 0);
                return;
            }
            int nRet = -1;
            IntPtr intPtr = m_pDeviceList.pDeviceInfo[cbDeviceList.SelectedIndex];

            // ch:获取选择的设备信息 | en:Get selected device information
            MyCamera.MV_CC_DEVICE_INFO device =
                (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[cbDeviceList.SelectedIndex], typeof(MyCamera.MV_CC_DEVICE_INFO));

            // ch:打开设备 | en:Open device
            if (null == m_pMyCamera)
            {
                m_pMyCamera = new MyCamera();
                if (null == m_pMyCamera)
                {
                    return;
                }
            }

            nRet = m_pMyCamera.MV_CC_CreateDevice_NET(ref device);
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            nRet = m_pMyCamera.MV_CC_OpenDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                m_pMyCamera.MV_CC_DestroyDevice_NET();
                ShowErrorMsg("设备打开失败!", nRet);
                return;
            }

            // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
            /*  if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
              {
                  int nPacketSize = m_pMyCamera.MV_CC_GetOptimalPacketSize_NET();
                  if (nPacketSize > 0)
                  {
                      nRet = m_pMyCamera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
                      if (nRet != MyCamera.MV_OK)
                      {
                          Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
                      }
                  }
                  else
                  {
                      Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
                  }
              }*/

            // ch:设置为触发模式
            TriggerMode();

            // ch:获取参数
            bnGetParam_Click(null, null);
        }

        /// <summary>
        /// 触发模式
        /// </summary>
        private void TriggerMode()
        {
            // ch:打开触发模式 | en:Open Trigger Mode
            m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerMode", 1);

            // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
            //           1 - Line1;
            //           2 - Line2;
            //           3 - Line3;
            //           4 - Counter;
            //           7 - Software;
            //软触发
            m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", 7);
            if (m_bGrabbing)
            {
                bnTriggerExec.Enabled = true;
            }

            cbSoftTrigger.Enabled = true;
        }

        /// <summary>
        /// 开始采集
        /// </summary>
        private void StartGrab()
        {
            int nRet;

            // ch:开始采集 | en:Start Grabbing
            nRet = m_pMyCamera.MV_CC_StartGrabbing_NET();
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Trigger Fail!", nRet);
                return;
            }

            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStartGrab();

            // ch:标志位置位true | en:Set position bit true
            m_bGrabbing = true;

            // ch:显示 | en:Display
            //取消原来的显示，改为halcon的显示方式
            nRet = m_pMyCamera.MV_CC_Display_NET(pictureBox1.Handle);

            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("显示失败！", nRet);
            }
        }

        /// <summary>
        /// 软触发一次
        /// </summary>
        private void TriggerExec()
        {
            int nRet;

            // ch:触发命令 | en:Trigger command
            nRet = m_pMyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
            if (MyCamera.MV_OK != nRet)
            {
                ShowErrorMsg("Trigger Fail!", nRet);
            }
        }

        #endregion

        #region 备份方法

        /// <summary>
        /// 直接加载本地图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadImage_Click_bk(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            //ofd.Filter = "Excel文件(*.xls;*.xlsx)|*.xls;*.xlsx|所有文件|*.*";
            //ofd.InitialDirectory = ".";
            //ofd.Filter = "所有文件(*.*)|*.*";
            ofd.Filter = "图像文件(*.bmp;*.jpg;*.jpeg;*.gif;*.png)|*.bmp;*.jpg;*.jpeg;*.gif;*.png";
            ofd.ValidateNames = true;
            ofd.CheckPathExists = true;
            ofd.CheckFileExists = true;

            if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName != string.Empty)
            {
                try
                {
                    string pathname = ofd.FileName;
                    //this.pictureBox1.Load(pathname);
                    CreateHalconWindow(pathname);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        public void CreateHalconWindow(string pathname)
        {
            HTuple FatherWindow = this.pictureBox1.Handle;

            //设置窗口的背景颜色
            HOperatorSet.SetWindowAttr("background_color", "red");
            this.pictureBox1.Load(pathname);
            HOperatorSet.OpenWindow(0, 0, this.pictureBox1.Width, this.pictureBox1.Height, FatherWindow, "visible", "", out WindowID);
        }

        #endregion

        //焊锡点
        public int[] tinStatus1 = new int[] { };

        //保存补偿值
        private void SaveOffset_Btn_Click(object sender, EventArgs e)
        {
            ImageDisposeDataService dataService = new ImageDisposeDataService();
            ImageDisposeData imageDispose = new ImageDisposeData();

            imageDispose.X1offset = X1offset_Nud.Value;
            imageDispose.Y1offset = Y1offset_Nud.Value;
            imageDispose.X2offset = X2offset_Nud.Value;
            imageDispose.Y2offset = Y2offset_Nud.Value;
            imageDispose.X3offset = X3offset_Nud.Value;
            imageDispose.Y3offset = Y3offset_Nud.Value;
            imageDispose.X4offset = X4offset_Nud.Value;
            imageDispose.Y4offset = Y4offset_Nud.Value;

            if (dataService.EditOffset(imageDispose))
            {
                MessageBox.Show("保存成功");
            }

            /* //将标定数据写入txt文件中
             StreamWriter sw1 = new StreamWriter(Application.StartupPath + "\\Argu\\DeviationValue.txt");
             StringBuilder sb = new StringBuilder();
             //标定的数据以；隔开，不去掉最后一个；
             sb.Append(Convert.ToString(Xoffset_Nud.Value)).Append(";").Append(Convert.ToString(Yoffset_Nud.Value));
             sw1.Write(sb.ToString());
             sw1.Close();
             MessageBox.Show("补偿保存成功");*/
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                Date_Lab.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("实时时间", ex);
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            //TODO每天10点执行定时任务
            int hour = DateTime.Now.Hour;
            if (hour == 10)
            {
                DeleteFolderAndFile();
            }
        }

        private void DeleteFolderAndFile()
        {
            //删除目录，保留3天数据
            string path = new StringBuilder(Application.StartupPath).Append("\\Image").ToString();

            DirectoryInfo dirs = new DirectoryInfo(path); //获得程序所在路径的目录对象
            DirectoryInfo[] dir = dirs.GetDirectories();//获得目录下文件夹对象
            //FileInfo[] file = dirs.GetFiles();//获得目录下文件对象
            int dircount = dir.Length;
            //获得文件夹对象数量
            //int filecount = file.Count();//获得文件对象数量
            string folder = DateTime.Today.AddDays(-1).ToString("yyyy-MM-dd");

            if (dircount > 1)
            {
                //删除目录和文件
                foreach (var item in dir)
                {
                    //把目录名转换成日期，比较大小
                    DateTime t1 = Convert.ToDateTime(folder);
                    DateTime t2 = Convert.ToDateTime(item.ToString());       //通过DateTIme.Compare()进行比较（）
                    int compNum = DateTime.Compare(t2, t1);         //t1> t2
                    if (compNum < 0 || compNum == 0)
                    {
                        if (item is DirectoryInfo)            //判断是否文件夹
                        {
                            DirectoryInfo subdir = new DirectoryInfo(item.FullName);
                            subdir.Delete(true);          //删除子目录和文件
                        }
                        //else
                        //{
                        //    //如果 使用了 streamreader 在删除前 必须先关闭流 ，否则无法删除 sr.close();
                        //    File.Delete(item.FullName);      //删除指定文件
                        //}
                    }
                }
            }
        }

        /// <summary>
        /// 删除文件夹及子文件内文件
        /// </summary>
        /// <param name="str"></param>
        public void DeleteFiles(string str)
        {
            DirectoryInfo fatherFolder = new DirectoryInfo(str);
            //删除当前文件夹内文件
            FileInfo[] files = fatherFolder.GetFiles();
            foreach (FileInfo file in files)
            {
                File.Delete(file.FullName);
            }
            //递归删除子文件夹内文件
            foreach (DirectoryInfo childFolder in fatherFolder.GetDirectories())
            {
                DeleteFiles(childFolder.FullName);
            }
        }

        /// <summary>
        /// 删除目录
        /// </summary>
        /// <param name="dir">要删除的目录</param>
        public static void DeleteFolder(string dir)
        {
            if (System.IO.Directory.Exists(dir))
            {
                string[] fileSystemEntries = System.IO.Directory.GetFileSystemEntries(dir);
                for (int i = 0; i < fileSystemEntries.Length; i++)
                {
                    string text = fileSystemEntries[i];
                    if (File.Exists(text))
                    {
                        File.Delete(text);
                    }
                    else
                    {
                        DeleteFolder(text);
                    }
                }
                Directory.Delete(dir);
            }
        }

        private void Roi_Save_Btn_Click(object sender, EventArgs e)
        {
            RoiValueService valueService = new RoiValueService();
            RoiValue roiValue = new RoiValue();
            roiValue.Row1 = roi_Row1.Value;
            roiValue.Column1 = roi_Column1.Value;
            roiValue.Row2 = roi_Row2.Value;
            roiValue.Column2 = roi_Column2.Value;
            if (valueService.UpdateRoiValue(roiValue))
            {
                ShowErrorMsg("保存成功", 0);
            }
        }

        private void Basic_FormClosed(object sender, FormClosedEventArgs e)
        {
            //停止监听
            CloseListen();
            //判断相机是否连接
            if (m_pMyCamera != null)
            {
                //关闭设备
                CloseDevice();
            }
        }

        public void CloseDevice()
        {
            // ch:关闭设备
            int nRet;

            nRet = m_pMyCamera.MV_CC_CloseDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            nRet = m_pMyCamera.MV_CC_DestroyDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                return;
            }

            // ch:控件操作
            SetCtrlWhenClose();

            // ch:取流标志位清零
            m_bGrabbing = false;
        }

        //保存锡点面积值
        private void TinValue_Btn_Click(object sender, EventArgs e)
        {
            ImageDisposeDataService dataService = new ImageDisposeDataService();
            ImageDisposeData imageDispose = new ImageDisposeData();
            imageDispose.TinValue = Convert.ToInt32(TinValue.Text);
            if (dataService.EditTinValue(imageDispose))
            {
                MessageBox.Show("保存成功！");
            }
        }

        /// <summary>
        /// Bitmap位图转halcon Hobject图像类型
        /// </summary>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        /// <param name="MyBitmap"></param>
        /// <returns></returns>
        public HObject BitmapToHobject(int Width, int Height, Bitmap MyBitmap)
        {
            HObject Image;

            BitmapData BitmapData = MyBitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
            unsafe
            {
                //图像数据排列BGR
                byte* Inptr = (byte*)(BitmapData.Scan0.ToPointer());
                byte[] R_OutBuffer = new byte[Width * Height];
                byte[] G_OutBuffer = new byte[Width * Height];
                byte[] B_OutBuffer = new byte[Width * Height];
                fixed (byte* R_Outptr = R_OutBuffer, G_Outptr = G_OutBuffer, B_Outptr = B_OutBuffer)
                {
                    for (int i = 0; i < Height; i++)
                    {
                        for (int j = 0; j < Width; j++)
                        {
                            int Index = (i * Width + j) * 4;
                            B_OutBuffer[Index / 4] = (byte)Inptr[Index + 0];
                            G_OutBuffer[Index / 4] = (byte)Inptr[Index + 1];
                            R_OutBuffer[Index / 4] = (byte)Inptr[Index + 2];
                        }
                    }
                    MyBitmap.UnlockBits(BitmapData);

                    HOperatorSet.GenImage3(out Image, "byte", Width, Height, new IntPtr(R_Outptr), new IntPtr(G_Outptr), new IntPtr(B_Outptr));

                    return Image;
                }
            }
        }

        #region 2.错误信息显示

        // ch:显示错误信息 | en:Show error message
        private void ShowErrorMsg(string csMessage, int nErrorNum)
        {
            string errorMsg;
            if (nErrorNum == 0)
            {
                errorMsg = csMessage;
            }
            else
            {
                errorMsg = csMessage + ": Error =" + String.Format("{0:X}", nErrorNum);
            }
            switch (nErrorNum)
            {
                case MyCamera.MV_E_HANDLE: errorMsg += " Error or invalid handle "; break;
                case MyCamera.MV_E_SUPPORT: errorMsg += " Not supported function "; break;
                case MyCamera.MV_E_BUFOVER: errorMsg += " Cache is full "; break;
                case MyCamera.MV_E_CALLORDER: errorMsg += " Function calling order error "; break;
                case MyCamera.MV_E_PARAMETER: errorMsg += " Incorrect parameter "; break;
                case MyCamera.MV_E_RESOURCE: errorMsg += " Applying resource failed "; break;
                case MyCamera.MV_E_NODATA: errorMsg += " No data "; break;
                case MyCamera.MV_E_PRECONDITION: errorMsg += " Precondition error, or running environment changed "; break;
                case MyCamera.MV_E_VERSION: errorMsg += " Version mismatches "; break;
                case MyCamera.MV_E_NOENOUGH_BUF: errorMsg += " Insufficient memory "; break;
                case MyCamera.MV_E_UNKNOW: errorMsg += " Unknown error "; break;
                case MyCamera.MV_E_GC_GENERIC: errorMsg += " General error "; break;
                case MyCamera.MV_E_GC_ACCESS: errorMsg += " Node accessing condition error "; break;
                case MyCamera.MV_E_ACCESS_DENIED: errorMsg += " No permission "; break;
                case MyCamera.MV_E_BUSY: errorMsg += " Device is busy, or network disconnected "; break;
                case MyCamera.MV_E_NETER: errorMsg += " Network error "; break;
            }
            MessageBox.Show(errorMsg, "提示");
        }

        #endregion 2.错误信息显示

        private void OnPaint(object sender, PaintEventArgs e)
        {
            Pen pen = new Pen(Color.Yellow, 1);
            Rectangle rectangle = new Rectangle(20, 20, 80, 40);
            e.Graphics.DrawRectangle(pen, rectangle);
            pen.Dispose();
        }
    }
}